home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Testing & Debugging / Virtual User tools / VU Assist Modules for MacApp / Assist Module MA 3.0 / VUAssist Source Code / UVUAssist.inc2.p < prev    next >
Encoding:
Text File  |  1993-09-17  |  34.4 KB  |  1,187 lines  |  [TEXT/MPS ]

  1. (*+
  2.  *    File:        UVUAssist.inc2.p - MacApp 3.0 compatible version
  3.  *
  4.  *    Contains:    VU assistance methods
  5.  *
  6.  *    Written by:    David Shayer
  7.  *
  8.  *    Copyright:    © 1991-92 by Apple Computer, Inc., all rights reserved.
  9.  *
  10.  *  Version: 1.0a1
  11.  *
  12.  *    Change History (most recent first):
  13.  
  14.          2/13/92    JAS        indicate 3.0 compatibility, change version
  15.          1/28/92    JAS        Make debugging writeln in SetDebuggerHook conditionally compiled
  16.          1/28/92    JAS        Removed cohandler install and setting of idle freq from IVUAssist
  17.          1/27/92    JAS        Removed call to FailNil in RankToItem
  18.          11/25/91    JAS        Remove call to Initialize in IVUAssist
  19.           10/4/91    JAS        indicate 3.0b2 compatibility, change version
  20.          9/10/91    JAS        indicate 3.0b2PQR compatibility, change version
  21.          8/21/91    JAS        adjust comments, change version
  22.          8/20/91    JAS        fix syntax error
  23.          8/20/91    JAS          remove debugging code
  24.          8/19/91    JAS        Revise comments, change case of GridItemSupport to
  25.                              gridItemSupport
  26.          8/15/91    JAS        Add GridItemSupport argument to IVUAssist
  27.          8/13/91    JAS        Revise comments
  28.          8/13/91    JAS        Change made in GetItemType so that kIncludeGridItems 
  29.                              will determine whether TGridItems are ever identified for use 
  30.          8/13/91    JAS        Make changes in IVUAssist since VUAssist is now a descendant
  31.                              of TEvtHandler (sets idle frequency and installs cohandler).
  32.          8/13/91    JAS        Changes in TGridItem implementation
  33.          8/13/91    JAS        Use FirstSubViewThat in place of EachSubView wherever applicable
  34.          8/6/91        JAS        Clean up change history
  35.          8/6/91        JAS        Check for GridViewItems in GetItemType only if DlogViewItems is
  36.                             true, remove TVUAssist.DoFindWindowInfo (not needed)
  37. -*)
  38.  
  39. {Historical Note:  References to the "Mole" are equivalent to references to "Agent VU".
  40. "Agent VU" was previously called the "Mole".}
  41.  
  42.  
  43. { The mole sees MacApp windows as plain windows that are empty.  MacApp
  44. doesn't put its controls in the control list, so V.U. won't even see standard
  45. Control Manager controls.  The assistance proc updates the mole buffer before
  46. it is sent back to the V.U. host, telling it that there are items in the windows, 
  47. and telling it about each item.  We tell it that the windows are dialogs, 
  48. because V.U. looks for a wider range of user interface items in dialogs.
  49.  
  50. V.U. has its own hierarchy of user interface items, based largely on the types of 
  51. interface items defined in Inside Mac which V.U. can obtain information about
  52. in non-MacApp applications.  MacApp's user interface element hierarchy is the View hierarchy.  
  53. Since the two hierarchies are not the same, VUAssist must perform a mapping between the
  54. two hierarchies.  Many of these mappings are straight-forward, but a few require some
  55. explanation.  The V.U. interface item hierarchy is as follows.  
  56.  
  57.                 |___ staticText
  58.                 |                       
  59.                 |___ editText                       
  60.                 |                                          
  61.                 |___ picture
  62. contentItem-----|
  63.                 |___ icon                       
  64.                 |                                          
  65.                 |___ userItem
  66.                 |
  67.                 |___ control-----|___ button
  68.                                   |                       
  69.                                   |___ checkBox    
  70.                                  |
  71.                                  |___ radioButton
  72.                                   |                       
  73.                                   |___ scrollBar
  74.                                  |                       
  75.                                   |___ popup
  76.                                  
  77. All V.U. interface items are considered contentItems.  Some of these contentItems are 
  78. typically found only in Dialog Manager dialogs in non-MacApp applications.  These would 
  79. be staticText, editText, picture, icon, and userItem.  Controls are Control Manager controls
  80. which may appear in any window.
  81.  
  82. The list of TView descendants which are mapped to V.U. interface items and the V.U. item
  83. to which they are mapped by V.U. by way of VUAssist is shown below.
  84.  
  85. TStaticText ---------> staticText
  86. TEditText     ---------> editText
  87. TPicture     ---------> picture
  88. TIcon         ---------> icon
  89. TButton     ---------> button
  90. TCheckbox     ---------> checkBox
  91. TRadio         ---------> radioButton
  92. TScrollBar     ---------> scrollBar
  93. TPopup         ---------> popup
  94. TTextEdit     ---------> editText
  95. (cells of TGridView -> contentItem)  - an optional feature
  96.  
  97. The last item, "cells of TGridView", deserves some explanation. TGridViews are a 
  98. problem because unlike all the other items mentioned above, where there is exactly one 
  99. MacApp object for each user interface item, there are many user interface items for a 
  100. single TGridView object.  V.U. does not yet directly support gridView types of objects.  
  101. So there is special case code for TGridViews.  Each cell in a grid is passed back as a 
  102. "CUSTOM_ITEM".  To V.U., a CUSTOM_ITEM is a user interface item which does not fall into
  103. any category more specific than contentItem.  So from a V.U. script writer's perspective,
  104. cells in TGridView objects are V.U. contentItems.
  105.  
  106. Note that the mapping of TGridView cells to contentItems is a feature which can be disabled.
  107. TVUAssist's IVUAssist method takes a boolean argument gridItemSupport.  By passing 'false'
  108. to this method, the cells of TGridViews are invisible to V.U..  You may want to do this if 
  109. your application has large gridviews or many gridviews.  In this case treating each cell as
  110. an interface item may bog down V.U. in such a way that performance is not acceptable. 
  111.  
  112. You'll also note in the code that we include TPopup descriptions in response to V.U.'s requests 
  113. for information about controls.  This is because V.U. can normally only support popups which 
  114. are implemented through the use of the popup CDEF found in System 7.0 or in the Mac Communications 
  115. Toolbox.  So V.U. expects them to be controls.}
  116.  
  117.  
  118.  
  119. {========================================== TVUAssist ================================}
  120.  
  121. {$S VUAssistSeg}
  122.  
  123. {The MoleHook is declared as type C, which means it must be an external function.
  124. The actual code for MoleHook is in assembly.  All it does is accept the call from the mole
  125. with a C interface, and then call TVUAssist.MoleAssist with a Pascal interface.}
  126. FUNCTION MoleHook (Select :integer; Input :Ptr; VAR OutputSize :integer;
  127.     Result :integer) :OSErr; C; EXTERNAL;
  128.  
  129.  
  130. { IVUAssist initializes fMoleRefNum.  fMoleRefNum contains the reference number of the 
  131. mole driver, or 0 if no mole driver has been found yet. Also initializes VUAssist as an EvtHandler, 
  132. sets idle frequency to kVUAssistIdleFreq, and installs cohandler.  Also initializes fGridItemSupport
  133. according to input argument gridItemSupport.}
  134. PROCEDURE TVUAssist.IVUAssist(gridItemSupport: boolean);
  135. BEGIN
  136.     INHERITED IEventHandler(NIL);
  137.     fGridItemSupport:=gridItemSupport;
  138.     fMoleRefNum:=0;
  139.     SELF.OpenMoleDriver;
  140. END;
  141.  
  142.  
  143. { Try to open the mole driver if there is one. }
  144. PROCEDURE TVUAssist.OpenMoleDriver;
  145. VAR
  146.     PBRec :ParamBlockRec;
  147.     Err :integer;
  148.     MoleName :Str15;
  149. BEGIN
  150.     MoleName:='.Mole';
  151.     PBRec.ioCompletion:=NIL;
  152.     PBRec.ioNamePtr:=@MoleName;
  153.     PBRec.ioPermssn:=fsCurPerm;
  154.     Err:=PBOpen (@PBRec, false);
  155.     IF (PBRec.ioResult=noErr) THEN
  156.     BEGIN
  157.         fMoleRefNum:=PBRec.ioRefNum;
  158.         SELF.ResumeMole;
  159.     END;
  160. END;
  161.  
  162.  
  163. { Call this routine when the application is suspended by Multifinder, to let
  164. the mole know we are no longer the frontmost app. }
  165. PROCEDURE TVUAssist.SuspendMole;
  166. BEGIN
  167.     SELF.SetDebuggerHook(NIL);
  168. END;
  169.  
  170.  
  171. { Call this routine when MultiFinder puts us back into the foreground. }
  172. PROCEDURE TVUAssist.ResumeMole; 
  173. BEGIN
  174.     SELF.SetDebuggerHook(@MoleHook);
  175. END;
  176.  
  177.  
  178.  
  179. { Tell the mole the address of our assistance procedure.}
  180. PROCEDURE TVUAssist.SetDebuggerHook (NewHook :ProcPtr); 
  181. CONST
  182.     SET_ASSIST = 100;
  183. VAR
  184.     PBRec :ParamBlockRec;
  185.     Err :integer;
  186.     LongPtr :^Longint;
  187. BEGIN
  188.     IF (fMoleRefNum<>0) THEN
  189.     BEGIN
  190.         PBRec.ioCompletion:=NIL;
  191.         PBRec.ioVRefNum:=0;
  192.         PBRec.ioRefNum:=fMoleRefNum;
  193.         PBRec.csCode:=SET_ASSIST;
  194.         LongPtr:=@PBRec.csParam[0];
  195.         LongPtr^:=LongInt(NewHook);
  196.         Err:=PBControl (@PBRec, false);
  197. {$IFC qDebug}
  198.         IF (PBRec.ioResult<>noErr) THEN
  199.             WriteLn ('Error sending Agent VU control call');    
  200. {$ENDC} 
  201.     END;
  202. END;
  203.  
  204.  
  205.  
  206. { This is the routine called by MoleHook.  It dispatches out to the routines
  207. which actually assist the mole. }
  208. FUNCTION TVUAssist.MoleAssist (Select :integer; Input :Ptr; Output :Ptr; 
  209.     VAR OutputSize :integer; IntResult :integer) :integer;
  210. VAR
  211.     Result        :MoleError;
  212.     ReturnValue    :MoleError;
  213. BEGIN
  214.     Result:=MoleError(IntResult);
  215.     ReturnValue:=Result;
  216.     CASE MoleSelectors(Select) OF
  217.         SMenuInfo:
  218.             BEGIN
  219.                 ReturnValue:=SELF.DoMenuInfo (Input, Output, OutputSize, Result);
  220.             END;
  221.         SMenuItems:
  222.             BEGIN
  223.                 ReturnValue:=SELF.DoMenuItems (Input, Output, OutputSize, Result);
  224.             END;
  225.         SetMItemKey:
  226.             BEGIN
  227.             END;
  228.         SFrontWind:
  229.             BEGIN
  230.             END;
  231.         SFindWind:
  232.             BEGIN
  233.             END;
  234.         SWindInfo:
  235.             BEGIN
  236.                 ReturnValue:=SELF.DoSendWindowInfo (Input, Output, OutputSize, Result);
  237.             END;
  238.         SFindCtl:
  239.             BEGIN
  240.                 ReturnValue:=SELF.DoFindControl (Input, Output, OutputSize, Result);
  241.             END;
  242.         SCtlInfo:
  243.             BEGIN
  244.                 ReturnValue:=SELF.DoSendControlInfo (Input, Output, OutputSize, Result);
  245.             END;
  246.         SFindDItem:
  247.             BEGIN
  248.             END;
  249.         SDItemInfo:
  250.             BEGIN
  251.                 ReturnValue:=SELF.DoSendDlogItemInfo (Input, Output, OutputSize, Result);
  252.             END;
  253.         OTHERWISE
  254.             BEGIN
  255.             END;
  256.     END; {case} 
  257.     MoleAssist:=integer(ReturnValue);
  258. END;
  259.  
  260.  
  261. {------------------------------------------------------------------------------------}
  262. { the routines for handling individual mole requests.  Each routine handles
  263.   exactly one mole request. }
  264.  
  265. { Handle a request for specific menu items.  The Mole can get info on menus in the
  266. menu bar, but we have to supply info on popup menus. }
  267. FUNCTION TVUAssist.DoMenuItems (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  268.     Result :MoleError) :MoleError;
  269. VAR
  270.     MenuReqPtr        :SendMenuItemsParamsPtr;
  271.     MenuDescPtr        :MoleDataBlockPtr;
  272.     Popup            :TPopup;
  273. BEGIN
  274.     DoMenuItems:=Result; {initially, inherit result from mole}
  275.     MenuReqPtr:=SendMenuItemsParamsPtr(Input);
  276.     MenuDescPtr:=MoleDataBlockPtr(Output);
  277.     
  278.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  279.     We do need to supply information about popups when the specified ID is non-zero. }
  280.     IF MenuReqPtr^.menu_ID<>0 THEN
  281.     BEGIN { find menu by menu ID }
  282.         IF (Result<>mNoErr) THEN
  283.         BEGIN
  284.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  285.             IF Popup<>NIL THEN
  286.             BEGIN
  287.                 DoMenuItems:=SELF.FillPopupItemDesc (Popup, RANK_OF_THE_INVISIBLE, 
  288.                     MenuReqPtr^.start_item, MenuReqPtr^.stop_item, MenuDescPtr, OutputSize);
  289.             END;
  290.         END;
  291.     END;
  292. END;
  293.  
  294.  
  295. { Handle a request for menu info.  The Mole can get info on menus in the
  296. menu bar, but we have to supply info on popup menus. }
  297. FUNCTION TVUAssist.DoMenuInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  298.     Result :MoleError) :MoleError;
  299. VAR
  300.     MenuReqPtr        :SendMenuInfoParamsPtr;
  301.     MenuDescPtr        :MoleMenuInfoPtr;
  302.     Popup            :TPopup;
  303. BEGIN
  304.     DoMenuInfo:=Result; {initially, inherit result from mole}
  305.     MenuReqPtr:=SendMenuInfoParamsPtr(Input);
  306.     MenuDescPtr:=MoleMenuInfoPtr(Output);
  307.     
  308.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  309.     We do need to supply information about popups when the specified ID is non-zero. }
  310.     IF MenuReqPtr^.menu_ID<>0 THEN
  311.     BEGIN { find menu by menu ID }
  312.         IF (Result<>mNoErr) THEN
  313.         BEGIN
  314.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  315.             IF Popup<>NIL THEN
  316.             BEGIN
  317.                 SELF.FillPopupDesc (Popup, RANK_OF_THE_INVISIBLE, MenuDescPtr, OutputSize);
  318.                 DoMenuInfo:=mNoErr;
  319.             END;
  320.         END;
  321.     END;
  322. END;
  323.  
  324.  
  325.  
  326. { Revise the values of the controlCount and numItems fields of the MoleWDescPtr, given
  327. knowledge of MacApp views. Also update validFlags and windowKind fields. WindowKind is set 
  328. to dialogKind so that V.U. will look for things that it can normally only see in dialogs 
  329. (such as icons and pictures) }
  330. FUNCTION TVUAssist.DoSendWindowInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  331.     Result :MoleError) :MoleError;
  332. VAR
  333.     WindReqPtr    :DWindReqPtr;
  334.     WindDescPtr    :MoleWDescPtr;
  335.     Window        :TWindow;
  336. BEGIN
  337.     DoSendWindowInfo:=Result; {initially, inherit result from mole}
  338.     WindReqPtr:=DWindReqPtr(Input);
  339.     WindDescPtr:=MoleWDescPtr(Output);
  340.     Window:=SELF.RankToWindow (WindReqPtr^);
  341.     IF Window<>NIL THEN 
  342.     BEGIN
  343.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VCTLCNT_MASK);
  344.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VITEMCNT_MASK);
  345.         WindDescPtr^.windowKind:=dialogKind;
  346.         WindDescPtr^.controlCount:=SELF.ViewCount (Window, false);
  347.         WindDescPtr^.numItems:=SELF.ViewCount (Window, true);
  348.         { OutputSize is filled in by the mole }
  349.         DoSendWindowInfo:=mNoErr;
  350.     END;
  351. END;
  352.  
  353.  
  354. { The mole sends us a point location in global coordinates.  We need to figure out
  355. which window and which control that point is in (if any), and send back info about
  356. that control. V.U. utilizes this routine for Control Manager controls (TCtlMgr) only.}
  357. FUNCTION TVUAssist.DoFindControl (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  358.     Result :MoleError) :MoleError;
  359. VAR
  360.     CtrlReqPtr    :SendFindControlParamPtr;
  361.     CtrlDescPtr    :MoleCDescPtr;
  362.     TargetPoint    :SendFindControlParam;
  363.     part        :integer;
  364.     wind        :WindowPeek;
  365.     SavePort    :GrafPtr;
  366.     Control        :TCtlMgr;
  367.     Rank        :integer;
  368.     SaveCtlList    :ControlHandle;
  369.     WhichCtl    :ControlHandle;
  370.     Window        :TWindow;
  371.     VPt            :VPoint;
  372. BEGIN
  373.     DoFindControl:=Result; {initially, inherit result from mole}
  374.     CtrlReqPtr:=SendFindControlParamPtr(Input);
  375.     TargetPoint:=CtrlReqPtr^;
  376.     CtrlDescPtr:=MoleCDescPtr(Output);
  377.  
  378.     part:=FindWindow (TargetPoint, WindowPtr(wind));
  379.     { The mole also tests for part=inSysWindow, but we'll let the mole handle those cases}
  380.     IF (wind<>NIL) AND (part=inContent) THEN
  381.     BEGIN
  382.         Window:=gApplication.WMgrToWindow(WindowPtr(wind));
  383.         IF (Window<>NIL) THEN
  384.         BEGIN
  385.             Control:=SELF.PointToControl (Window, TargetPoint, Rank);
  386.             IF Control<>NIL THEN
  387.             BEGIN
  388.                 part:=-1;
  389.                 { Get the control part code.  Controls are not kept in the controllist,
  390.                 so we temporarily put them in there.  Also, they are in their subviews
  391.                 local coordinate system, so we must convert targetpoint. }
  392.                 GetPort (SavePort);
  393.                 SetPort (WindowPtr(wind));
  394.                 IF Window.Focus THEN
  395.                 BEGIN
  396.                     SaveCtlList:=wind^.controlList;
  397.                     wind^.controlList:=Control.fCMgrControl;
  398.                     SELF.GlobalToWindow (Window, TargetPoint, VPt);
  399.                     SELF.WindowToView (Control, VPt, TargetPoint);
  400.                     part:=FindControl (TargetPoint, WindowPtr(wind), WhichCtl);
  401.                     wind^.controlList:=SaveCtlList;
  402.                 END;
  403.                 SetPort (SavePort);
  404.                 
  405.                 IF (SELF.FillCtrlDesc (CtrlDescPtr, part, SELF.WindowToRank(wind), 
  406.                     Rank, Control, OutputSize)) THEN
  407.                 BEGIN
  408.                     DoFindControl:=mNoErr;
  409.                 END;
  410.             END;
  411.         END;
  412.     END;
  413. END;
  414.  
  415.  
  416. { Read the input parameter to see which control V.U. wants info on, then
  417. fill in the SendCtlInfoParamsPtr record.  The mole can't gather any info about
  418. MacApp controls without our help, so we fill in the whole record, except for part, 
  419. which doesn't apply.}
  420. FUNCTION TVUAssist.DoSendControlInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  421.     Result :MoleError) :MoleError;
  422. VAR
  423.     CtrlReqPtr    :SendCtlInfoParamsPtr;
  424.     CtrlDescPtr    :MoleCDescPtr;
  425.     Window        :TWindow;
  426.     Control        :TControl;
  427.     gridItem    :TGridItem;
  428. BEGIN
  429.     DoSendControlInfo:=Result; {initially, inherit result from mole}
  430.     gridItem:=NIL;
  431.     CtrlReqPtr:=SendCtlInfoParamsPtr(Input);
  432.     CtrlDescPtr:=MoleCDescPtr(Output);
  433.  
  434.     Window:=SELF.RankToWindow (CtrlReqPtr^.window_rank);
  435.     IF Window<>NIL THEN
  436.     BEGIN
  437.         Control:=TControl(SELF.RankToItem (Window, CtrlReqPtr^.control_rank, false, gridItem));
  438.         IF Control<>NIL THEN
  439.         BEGIN
  440.             IF (SELF.FillCtrlDesc (CtrlDescPtr, -1, CtrlReqPtr^.window_rank, 
  441.                 CtrlReqPtr^.control_rank, Control, OutputSize)) THEN
  442.             BEGIN
  443.                 DoSendControlInfo:=mNoErr;
  444.             END;
  445.         END;
  446.     END;
  447. END;
  448.  
  449.  
  450. { Read the input to see which dialog item in which window V.U. wants data on, and
  451. fill in the dialogiteminfo record. }
  452. FUNCTION TVUAssist.DoSendDlogItemInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  453.     Result :MoleError) :MoleError;
  454. VAR
  455.     DlogReqPtr    :SendDItemInfoPtr;
  456.     DlogDescPtr    :MoleDItemInfoPtr;
  457.     Window        :TWindow;
  458.     View        :TView;
  459.     gridItem    :TGridItem;
  460. BEGIN
  461.     DoSendDlogItemInfo:=Result; {initially, inherit result from mole}
  462.     gridItem:=NIL;
  463.     DlogReqPtr:=SendDItemInfoPtr(Input);
  464.     DlogDescPtr:=MoleDItemInfoPtr(Output);
  465.     
  466.     Window:=SELF.RankToWindow (DlogReqPtr^.window_rank);
  467.     IF Window<>NIL THEN
  468.     BEGIN
  469.         View:=SELF.RankToItem (Window, DlogReqPtr^.item_num, true, gridItem);
  470.         IF View<>NIL THEN
  471.         BEGIN
  472.             SELF.FillDlogItemDesc (DlogDescPtr, Window, DlogReqPtr^.window_rank, 
  473.                 DlogReqPtr^.item_num, View, OutputSize, gridItem);
  474.             DoSendDlogItemInfo:=mNoErr;
  475.         END;
  476.     END;
  477. END;
  478.  
  479.  
  480. {------------------------------------------------------------------------------------}
  481. { routines for filling in mole data structures }
  482.  
  483. { Given a TPopup object, fill in the mole's menu descriptor record. }
  484. PROCEDURE TVUAssist.FillPopupDesc (Popup: TPopup; MenuRank: integer; 
  485.     MenuDescPtr :MoleMenuInfoPtr; VAR OutputSize :integer);
  486. VAR
  487.     TheMenuHdl    :MenuHandle;
  488. BEGIN
  489.     TheMenuHdl := Popup.GetMenuHandle;
  490.     WITH MenuDescPtr^ DO
  491.     BEGIN
  492.         num_items:=CountMItems (TheMenuHdl);
  493.         rank:=MenuRank;
  494.         left_edge:=0;
  495.         menuID:=Popup.GetMenuID;
  496.         menuWidth:=TheMenuHdl^^.menuWidth;
  497.         menuHeight:=TheMenuHdl^^.menuHeight;
  498.         enableFlags:=TheMenuHdl^^.enableFlags;
  499.         text_name:=TheMenuHdl^^.menuData;
  500.         
  501.         { this ugly thing computes the length (bytes used) of MoleMenuInfo }
  502.         OutputSize:=sizeof(MoleMenuInfo) - (255-length(text_name));
  503.     END;
  504. END;
  505.  
  506.  
  507. { Given a TPopup object, fill in the mole's menuitem descriptor record. }
  508. FUNCTION TVUAssist.FillPopupItemDesc (Popup: TPopup; MenuRank: integer; start: integer; 
  509.     stop: integer; MenuItemDescPtr :MoleDataBlockPtr; VAR OutputSize :integer) :MoleError;
  510.     
  511.     { this function depends upon Ptr being a pointer to a single byte }
  512.     FUNCTION SeekMenuItem (ItemNum: integer; MenuHdl: MenuHandle) :Ptr;
  513.     VAR
  514.         SeekPtr    :Ptr;
  515.         SeekNum    :integer;
  516.     BEGIN
  517.         SeekNum:=1;
  518.         SeekPtr:= Ptr(ORD4(@MenuHdl^^.menuData) + length(MenuHdl^^.menuData) + 1);
  519.         WHILE (SeekNum<ItemNum) AND (SeekPtr^<>0) DO
  520.         BEGIN
  521.             SeekPtr:= Ptr(ORD4(SeekPtr) + SeekPtr^ + ADDITIONAL_MENU_ITEM_DATA);
  522.             SeekNum:=SeekNum+1;
  523.         END;
  524.         SeekMenuItem:=SeekPtr;
  525.     END;
  526.     
  527. VAR
  528.     StartPtr    :Ptr;
  529.     StopPtr        :Ptr;VAR
  530.     TheMenuHdl    :MenuHandle;
  531. BEGIN
  532.     
  533.     TheMenuHdl := Popup.GetMenuHandle;
  534.     
  535.     FillPopupItemDesc:=mNoErr;
  536.     IF (start>CountMItems (TheMenuHdl)) OR (start<1) THEN
  537.     BEGIN
  538.         FillPopupItemDesc:=mBadMenuItemIndex;
  539.         EXIT (FillPopupItemDesc);
  540.     END;
  541.     
  542.     IF stop>CountMItems (TheMenuHdl) THEN
  543.     BEGIN
  544.         stop:=CountMItems (TheMenuHdl);
  545.         FillPopupItemDesc:=mBadLastMenuItemIndex;
  546.     END;
  547.     
  548.     StartPtr:=SeekMenuItem (start, TheMenuHdl);
  549.     StopPtr:=SeekMenuItem (stop+1, TheMenuHdl);
  550.     IF (StartPtr=NIL) OR (StopPtr=NIL) THEN
  551.     BEGIN
  552.         FillPopupItemDesc:=mBadMenuItemIndex;
  553.         EXIT (FillPopupItemDesc);
  554.     END;
  555.     MenuItemDescPtr^.blockLength:=stop-start+1;
  556.     BlockMove (StartPtr, @MenuItemDescPtr^.dataBlock[0], ORD4(StopPtr)-ORD4(StartPtr));
  557.     
  558.     { this ugly thing computes the length (bytes used) of MoleDataBlock }
  559.     OutputSize:=sizeof(integer) + (ORD4(StopPtr)-ORD4(StartPtr));
  560. END;
  561.  
  562.  
  563. { Fill in a mole control descriptor record.  Valid descendants of TControl are descendants of
  564. TCtlMgr and TPopup. Will return false if TControl is not a descendant of TCtlMgr or TPopup.}
  565. FUNCTION TVUAssist.FillCtrlDesc (CtrlDescPtr :MoleCDescPtr; thePart :integer; 
  566.     WindRank :integer; ControlRank :integer; Control :TControl; VAR OutputSize :integer): BOOLEAN;
  567. VAR
  568.     dummy        :longint;
  569.     ControlHdl    :ControlHandle;
  570.     aVRect        :VRect;
  571.     TheMenuHdl    :MenuHandle;
  572. BEGIN
  573.     FillCtrlDesc:=FALSE; 
  574.     IF Member (Control, TPopup) THEN
  575.     BEGIN
  576.         TheMenuHdl := TPopup(Control).GetMenuHandle;
  577.         WITH CtrlDescPtr^ DO
  578.         BEGIN
  579.             validFlags:=VALL_C_MASK;
  580.             IF thePart=-1 THEN
  581.             BEGIN
  582.                 dummy:=validFlags;
  583.                 BClr (dummy, VCPART);
  584.                 validFlags:=dummy;
  585.             END;
  586.             owner_rank:=WindRank;
  587.             Control.GetExtent (aVRect);
  588.             VRectToRect(aVRect, ctlRect);
  589.             SELF.ViewRectToWindowRect (ctlRect, Control);
  590.  
  591.             ctlValue:=TPopup(Control).GetCurrentItem;
  592.             ctlMin:=1;
  593.             ctlMax:=CountMItems(TheMenuHdl);
  594.             ctlHilite:=0;
  595.             IF thePart=-1 THEN
  596.                 part:=0
  597.             ELSE
  598.                 part:=thePart;
  599.             ctlRank:=ControlRank;
  600.             ctlDefID:=POPUP_CDEF*16;
  601.             popupMenuID:=TPopup(Control).GetMenuID;
  602.             text_name:=TheMenuHdl^^.menuData;
  603.     
  604.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  605.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  606.         END;
  607.     END
  608.     ELSE IF Member (Control, TCtlMgr) THEN {non-popup member of TCtlMgr}
  609.     BEGIN
  610.         ControlHdl:=TCtlMgr(Control).fCMgrControl;
  611.         WITH CtrlDescPtr^, ControlHdl^^ DO
  612.         BEGIN
  613.             validFlags:=VALL_C_MASK;
  614.             IF thePart=-1 THEN
  615.             BEGIN
  616.                 dummy:=validFlags;
  617.                 BClr (dummy, VCPART);
  618.                 validFlags:=dummy;
  619.             END;
  620.             owner_rank:=WindRank;
  621.             ctlRect:=contrlRect;
  622.             SELF.ViewRectToWindowRect (ctlRect, Control);
  623.             ctlValue:=contrlValue;
  624.             ctlMin:=contrlMin;
  625.             ctlMax:=contrlMax;
  626.             ctlHilite:=contrlHilite;
  627.             IF thePart=-1 THEN
  628.                 part:=0
  629.             ELSE
  630.                 part:=thePart;
  631.             ctlRank:=ControlRank;
  632.             ctlDefID:=BAND(BSR(longint(contrlDefProc), 24), $7);
  633.             IF Member (Control, TScrollBar) THEN
  634.                 ctlDefID:=ctlDefID+16;
  635.             popupMenuID:=0;
  636.             text_name:=contrlTitle;
  637.     
  638.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  639.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  640.             FillCtrlDesc:=TRUE;
  641.         END;
  642.     END;
  643. END;
  644.  
  645.  
  646. PROCEDURE TVUAssist.ViewRectToWindowRect (VAR aRect :Rect; aView :TView);
  647. VAR
  648.     VPt :VPoint;
  649. BEGIN
  650.     PtToVPt(aRect.topLeft, VPt);
  651.     aView.LocalToWindow (VPt);
  652.     aRect.topLeft:=VPtToPt (VPt);
  653.     PtToVPt(aRect.botRight, VPt);
  654.     aView.LocalToWindow (VPt);
  655.     aRect.botRight:=VPtToPt (VPt);
  656. END;
  657.  
  658.  
  659. { Fill in a mole dialog item descriptor record }
  660. PROCEDURE TVUAssist.FillDlogItemDesc (DlogDescPtr :MoleDItemInfoPtr; Window :TWindow;
  661.     WindRank :integer; ItemRank :integer; Item :TView; VAR OutputSize :integer; gridItem :TGridItem);
  662. VAR
  663.     aVRect        :VRect;
  664.     TextLen     :longint;
  665.     TextHdl     :Handle;
  666.     ItemKind    :ViewItems;
  667.     aCell        :GridCell;
  668.     VBox        :VRect;        
  669. BEGIN
  670.     WITH DlogDescPtr^ DO
  671.     BEGIN
  672.         ItemKind:=SELF.GetItemType (Item, true, true);
  673.         { fill in box, itemType, item_enabled, has_text and text_name here }
  674.         CASE ItemKind OF
  675.             VINotMember:
  676.                 ;
  677.             VIButton:
  678.             BEGIN
  679.                 TCtlMgr(Item).ControlArea (VBox);
  680.                 VRectToRect(VBox, box);
  681.                 itemType:=btnCtrlItem;
  682.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  683.                 has_text:=TRUE;
  684.                 TCtlMgr(Item).GetText (text_name);
  685.             END;
  686.             VIRadio:
  687.             BEGIN
  688.                 TCtlMgr(Item).ControlArea (VBox);
  689.                 VRectToRect(VBox, box);
  690.                 itemType:=radCtrlItem;
  691.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  692.                 has_text:=TRUE;
  693.                 TCtlMgr(Item).GetText (text_name);
  694.             END;
  695.             VICheckBox:
  696.             BEGIN
  697.                 TCtlMgr(Item).ControlArea (VBox);
  698.                 VRectToRect(VBox, box);
  699.                 itemType:=chkCtrlItem;
  700.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  701.                 has_text:=TRUE;
  702.                 TCtlMgr(Item).GetText (text_name);
  703.             END;
  704.             VIScrollBar:
  705.             BEGIN
  706.                 TCtlMgr(Item).ControlArea (VBox);
  707.                 VRectToRect(VBox, box);
  708.                 itemType:=resCtrlItem;
  709.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  710.                 has_text:=TRUE;
  711.                 TCtlMgr(Item).GetText (text_name);
  712.             END;
  713.             VIStatText:
  714.             BEGIN
  715.                 Item.GetExtent (aVRect);
  716.                 VRectToRect(aVRect, box);
  717.                 itemType:=statText;
  718.                 item_enabled:=FALSE;
  719.                 has_text:=TRUE;
  720.                 TStaticText(Item).GetText (text_name);
  721.             END;
  722.             VIEditText:
  723.             BEGIN
  724.                 Item.GetExtent (aVRect);
  725.                 VRectToRect(aVRect, box);
  726.                 itemType:=editText;
  727.                 item_enabled:=Item.IsActive;
  728.                 has_text:=TRUE;
  729.                 TStaticText(Item).GetText (text_name);
  730.             END;
  731.             VIIcon:
  732.             BEGIN
  733.                 Item.GetExtent (aVRect);
  734.                 VRectToRect(aVRect, box);
  735.                 itemType:=iconItem;
  736.                 item_enabled:=Item.IsActive;
  737.                 has_text:=FALSE;
  738.                 item_text_ptr:=NIL;
  739.             END;
  740.             VIPopup:
  741.             BEGIN
  742.                 Item.GetExtent (aVRect);
  743.                 VRectToRect(aVRect, box);
  744.                 itemType:=resCtrlItem;
  745.                 item_enabled:=Item.IsActive;
  746.                 has_text:=FALSE;
  747.                 item_text_ptr:=NIL;
  748.             END;
  749.             VIPicture:
  750.             BEGIN
  751.                 Item.GetExtent (aVRect);
  752.                 VRectToRect(aVRect, box);
  753.                 itemType:=picItem;
  754.                 item_enabled:=Item.IsActive;
  755.                 has_text:=FALSE;
  756.                 item_text_ptr:=NIL;
  757.             END;
  758.             VITextEdit:
  759.             BEGIN
  760.                 Item.GetExtent (aVRect);
  761.                 VRectToRect(aVRect, box);
  762.                 itemType:=editText;
  763.                 item_enabled:=Item.IsActive;
  764.                 has_text:=TRUE;
  765.                 TextHdl:=TTEView(Item).ExtractText;
  766.                 TextLen:=GetHandleSize (TextHdl);
  767.                 IF TextLen>255 THEN TextLen:=255;
  768.                 BlockMove (TextHdl^, @text_name, TextLen);
  769.             END;
  770.             VIGridItem:
  771.             BEGIN
  772.                 gridItem.GetExtent (aVRect);
  773.                 VRectToRect(aVRect, box);
  774.                 itemType:=CUSTOM_ITEM;
  775.                 item_enabled:=gridItem.fGridView.IsActive;
  776.                 IF Member (Item, TTextGridView) THEN
  777.                 BEGIN  {item has text associated with it}
  778.                     has_text:=TRUE;
  779.                     aCell.v:=gridItem.fRow;
  780.                     aCell.h:=gridItem.fColumn;
  781.                     TTextGridView(gridItem.fGridView).GetText (aCell, text_name);
  782.                 END
  783.                 ELSE   {item may not have text associated with it}
  784.                 BEGIN
  785.                     has_text:=FALSE;
  786.                     item_text_ptr:=NIL;
  787.                 END;
  788.             END;
  789.         END; { case }
  790.         SELF.ViewRectToWindowRect (box, Item);
  791.         { fill in ctlRank, owner_rank, and item_num here }
  792.         ctlRank:=SELF.ItemToRank (Window, Item, false);
  793.         owner_rank:=WindRank;
  794.         item_num:=ItemRank;
  795.             
  796.         { this ugly thing computes the length (bytes used) of MoleDItemInfo }
  797.         IF ItemKind<>VINotMember THEN
  798.             OutputSize:=sizeof(MoleDItemInfo) - (255-length(text_name));
  799.         
  800.         IF gridItem <> NIL THEN
  801.             gridItem.Free;
  802.     END; { with }
  803. END;
  804.  
  805.  
  806. {------------------------------------------------------------------------------------}
  807. { routines for searching through the view tree to find particular views }
  808.  
  809. { Given the rank (z-order) of a window, return the window object.  Invisible
  810. windows are not considered to be in the window list, for ranking purposes. }
  811. FUNCTION TVUAssist.RankToWindow (Rank :integer) :TWindow;
  812. VAR
  813.     i: integer;
  814.     Window :WindowPeek;
  815. BEGIN
  816.     RankToWindow:=NIL;
  817.     i:=1;
  818.     Window:=WindowPeek(FrontWindow);
  819.     WHILE Window<>NIL DO
  820.     BEGIN
  821.         IF Window^.visible THEN
  822.         BEGIN
  823.             IF i=Rank THEN
  824.             BEGIN
  825.                 RankToWindow:=gApplication.WMgrToWindow(WindowPtr(Window));
  826.                 LEAVE;
  827.             END;
  828.             i:=i+1;
  829.         END;
  830.         Window:=Window^.nextWindow;
  831.     END;
  832. END;
  833.  
  834.  
  835. {Given a window ptr, return the window's rank (z-order).}
  836. FUNCTION TVUAssist.WindowToRank (WindToFind :WindowPeek) :integer;
  837. VAR
  838.     i: integer;
  839.     Window :WindowPeek;
  840. BEGIN
  841.     WindowToRank:=0;
  842.     i:=1;
  843.     Window:=WindowPeek(FrontWindow);
  844.     WHILE Window<>NIL DO
  845.     BEGIN
  846.         IF Window^.visible THEN
  847.         BEGIN
  848.             IF WindToFind=Window THEN
  849.             BEGIN
  850.                 WindowToRank:=i;
  851.                 LEAVE;
  852.             END;
  853.             i:=i+1;
  854.         END;
  855.         Window:=Window^.nextWindow;
  856.     END;
  857. END;
  858.  
  859.  
  860. { Convert a point in global coordinates to window coordinates. }
  861. PROCEDURE TVUAssist.GlobalToWindow (Window :TWindow; Pt :Point; VAR VPt :VPoint);
  862. VAR
  863.     SavePort    :GrafPtr;
  864.     TargetPoint    :Point;
  865. BEGIN
  866.     VPt.h:=0;
  867.     VPt.v:=0;
  868.     GetPort (SavePort);
  869.     SetPort (Window.GetGrafPort);
  870.     IF Window.Focus THEN
  871.     BEGIN
  872.         TargetPoint:=Pt;
  873.         GlobalToLocal (TargetPoint);
  874.         Window.QDToViewPt(TargetPoint, VPt);
  875.     END;
  876.     SetPort (SavePort);
  877. END;
  878.  
  879.  
  880. { Convert a point in window coordinates to a subview's coordinates. Return both a
  881. VPoint and a QDPoint. }
  882. PROCEDURE TVUAssist.WindowToView (View :TView; VAR VPt :VPoint; VAR Pt :Point);
  883. BEGIN
  884.     Pt.h:=0;
  885.     Pt.v:=0;
  886.     View.WindowToLocal(VPt);
  887.     IF View.Focus THEN
  888.         Pt:=View.ViewToQDPt (VPt);
  889. END;
  890.  
  891.  
  892.  
  893. { In the front (active) window, given the menu ID of a popup item, return the  
  894. popup menu object and its rank. }
  895. FUNCTION TVUAssist.MenuIDToPopup (MenuID :integer) :TPopup;
  896. VAR
  897.     foundView     :TView;
  898.     dummyView    :TView;
  899.     window        :TWindow;
  900.     
  901.     FUNCTION TestSubID(theSubView: TView): BOOLEAN;
  902.     BEGIN
  903.         IF theSubView.IsShown THEN
  904.         BEGIN    
  905.             IF SELF.GetItemType (theSubView, false, false)=VIPopup THEN
  906.             BEGIN
  907.                 IF TPopup(theSubView).fMenuID=MenuID THEN
  908.                     foundView:=theSubView;
  909.             END;
  910.             IF (foundView=NIL) THEN
  911.                 dummyView:=theSubView.FirstSubViewThat (TestSubID);
  912.         END;
  913.         TestSubID:=foundView <> NIL;
  914.     END;
  915.     
  916. BEGIN
  917.     foundView:=NIL;
  918.     window:=gApplication.GetActiveWindow;
  919.     IF (Window<>NIL) & (Window.IsShown) THEN
  920.         dummyView:=Window.FirstSubViewThat (TestSubID);
  921.     MenuIDToPopup:=TPopup(foundView);
  922. END;
  923.  
  924.  
  925. { Given a window object and a point in global coordinates,
  926. find the control which is under that point. Only descendants of
  927. TCtlMgr are considered.}
  928. FUNCTION TVUAssist.PointToControl (Window :TWindow; Pt :Point; VAR Rank :integer) :TCtlMgr;
  929. VAR
  930.     foundView     : TView;
  931.     dummyView    : TView;
  932.     VPt            : VPoint;
  933.     TestPoint    : VPoint;
  934.     DummyPoint    : Point;
  935.     aRect        : Rect;
  936.     
  937.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  938.     VAR
  939.         ItemType :ViewItems;
  940.     BEGIN
  941.         IF theSubView.IsShown THEN
  942.         BEGIN    
  943.             IF Member (theSubView, TCtlMgr) THEN
  944.             BEGIN
  945.                 TestPoint:=VPt;
  946.                 SELF.WindowToView (theSubView, TestPoint, DummyPoint);
  947.                 IF theSubView.ContainsMouse(TestPoint) THEN
  948.                     foundView:=theSubView;
  949.             END;
  950.             IF (foundView=NIL) THEN
  951.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  952.         END;
  953.         TestSubView:=foundView <> NIL;
  954.     END;
  955.     
  956. BEGIN
  957.     foundView:=NIL;
  958.     SELF.GlobalToWindow (Window, Pt, VPt);
  959.     IF Window.IsShown THEN
  960.         dummyView:=Window.FirstSubViewThat (TestSubView);
  961.     Rank:=SELF.ItemToRank (Window, foundView, false);
  962.     PointToControl:=TCtlMgr(foundView);
  963. END;
  964.  
  965.  
  966. { Walk the view hierarchy tree, counting the number of user interface items.
  967. Only visible views and items are counted. }
  968. FUNCTION TVUAssist.ViewCount (Window :TWindow; DlogViewItems :Boolean) :integer;
  969. VAR
  970.     ItemCount :integer;
  971.     
  972.     PROCEDURE DoToSubView(theSubView: TView);
  973.     VAR
  974.         ItemType: ViewItems;
  975.     BEGIN
  976.         IF theSubView.IsShown THEN
  977.         BEGIN
  978.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  979.             IF ItemType<>VINotMember THEN
  980.             BEGIN
  981.                 IF ItemType=VIGridItem THEN
  982.                     ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView))
  983.                 ELSE
  984.                     ItemCount := ItemCount + 1;
  985.             END;
  986.             IF Member (theSubView, TView) THEN
  987.                 theSubView.EachSubView (DoToSubView);
  988.         END;
  989.     END;
  990.     
  991. BEGIN
  992.     ItemCount:=0;
  993.     IF Window.IsShown THEN
  994.         Window.EachSubView (DoToSubView);
  995.     ViewCount:=ItemCount;
  996. END;
  997.  
  998.  
  999. {Given a control or dialog item (View), and the window its in (Window), return its rank. }
  1000. FUNCTION TVUAssist.ItemToRank (Window :TWindow; View :TView; DlogViewItems :Boolean) :integer;
  1001. VAR
  1002.     ItemCount    :integer;
  1003.     Rank         :integer;
  1004.     dummyView    :TView;
  1005.     
  1006.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1007.     VAR
  1008.         ItemType:    ViewItems;
  1009.     BEGIN
  1010.         IF theSubView.IsShown THEN
  1011.         BEGIN    
  1012.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1013.             IF ItemType<>VINotMember THEN
  1014.             BEGIN
  1015.                 IF ItemType=VIGridItem THEN
  1016.                 BEGIN
  1017.                     IF (Member(View, TGridItem)) & (theSubView=TGridItem(View).fGridView) THEN
  1018.                         Rank:=ItemCount+TGridItem(View).fRank
  1019.                     ELSE
  1020.                         ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView));
  1021.                 END
  1022.                 ELSE BEGIN
  1023.                     ItemCount := ItemCount + 1;
  1024.                     IF theSubView=View THEN
  1025.                         Rank:=ItemCount;
  1026.                 END;
  1027.             END;
  1028.             IF (Rank=0) THEN
  1029.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1030.         END;
  1031.         TestSubView:=Rank <> 0;
  1032.     END;
  1033.     
  1034. BEGIN
  1035.     Rank:=0;    
  1036.     ItemCount:=0;
  1037.     IF Window.IsShown THEN
  1038.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1039.     ItemToRank:=Rank;
  1040. END;
  1041.  
  1042.  
  1043. { Given a window object and the rank (z-order) of an item, return the item object. If
  1044. the item is a cell of a TGridView object, return that object in gridItem.}
  1045. FUNCTION TVUAssist.RankToItem (Window :TWindow; Rank :integer; DlogViewItems :Boolean;
  1046.                                VAR gridItem: TGridItem) :TView;
  1047. VAR
  1048.     ItemCount    :integer;
  1049.     foundView     :TView;
  1050.     dummyView    :TView;
  1051.     
  1052.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1053.     VAR
  1054.         ItemType:    ViewItems;
  1055.         GridCount:    integer;
  1056.     BEGIN
  1057.         IF theSubView.IsShown THEN
  1058.         BEGIN    
  1059.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1060.             IF ItemType<>VINotMember THEN
  1061.             BEGIN
  1062.                 IF (ItemType=VIGridItem) THEN
  1063.                 BEGIN
  1064.                     GridCount:=SELF.CountGridItems (TGridView(theSubView));
  1065.                     IF (Rank>ItemCount) AND (Rank<=ItemCount+GridCount) THEN
  1066.                     BEGIN
  1067.                         New (gridItem);
  1068.                         gridItem.IGridItem (TGridView(theSubView), Rank-ItemCount);
  1069.                         foundView:=theSubView;
  1070.                     END;
  1071.                     ItemCount := ItemCount + GridCount;
  1072.                 END
  1073.                 ELSE BEGIN
  1074.                     ItemCount := ItemCount + 1;
  1075.                     IF ItemCount=Rank THEN
  1076.                         foundView:=theSubView;
  1077.                 END;
  1078.             END;
  1079.             IF (foundView=NIL) THEN
  1080.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1081.         END;
  1082.     TestSubView:=foundView <> NIL;
  1083.     END;
  1084.     
  1085. BEGIN
  1086.     foundView:=NIL;
  1087.     ItemCount:=0;
  1088.     IF Window.IsShown THEN
  1089.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1090.     RankToItem:=foundView;
  1091. END;
  1092.  
  1093.  
  1094. { Report the number of items in a TGridView.  This is here so it can
  1095. be easily overridden if you only want rows or columns to show up as
  1096. seperate user interface items, instead of each cell. }
  1097. FUNCTION TVUAssist.CountGridItems (theGridView: TGridView): integer;
  1098. BEGIN
  1099.     CountGridItems:=theGridView.fNumOfRows*theGridView.fNumOfCols;
  1100. END;
  1101.  
  1102.  
  1103.  
  1104. {Given a view item and the control/dialog item flag, decide if this
  1105. view object is a control if the flag=ControlsOnly, or if its a dialog
  1106. item if the flag=DialogItems, or if its neither.  Of course, MacApp 
  1107. doesn't have a concept of dialog items, so we improvise.  Here are the criteria.
  1108. Any descendent of TCtlMgr is a control.  Descendants of TPopup are also classified
  1109. as contols because V.U. can normally only deal with popups which utilize the popup
  1110. CDEF.  So V.U. expects popups to be controls.
  1111.  
  1112. Descendents of TTEView and some descendants of TControl (specifically TEditText, 
  1113. TStaticText, TIcon, TPicture, and TGridView) are considered to be DialogItems for V.U.'s sake.  
  1114. GridViewItems are considered along with other DlogViewItems only if GridViewItems parameter 
  1115. is true.}
  1116. FUNCTION TVUAssist.GetItemType (Item :TView; DlogViewItems :Boolean;
  1117.     GridViewItems: Boolean) :ViewItems;
  1118. BEGIN
  1119.     GetItemType:=VINotMember;
  1120.     IF Member (Item, TPopup) THEN
  1121.         GetItemType:=VIPopup
  1122.     ELSE IF Member (Item, TRadio) THEN
  1123.         GetItemType:=VIRadio
  1124.     ELSE IF Member (Item, TCheckBox) THEN
  1125.         GetItemType:=VICheckBox
  1126.     ELSE IF Member (Item, TScrollBar) THEN
  1127.         GetItemType:=VIScrollBar
  1128.     ELSE IF Member (Item, TButton) THEN    
  1129.         GetItemType:=VIButton;            
  1130.     IF DlogViewItems THEN                
  1131.     BEGIN
  1132.         IF Member (Item, TEditText) THEN    {TEditText descends from TStaticText}
  1133.             GetItemType:=VIEditText
  1134.         ELSE IF Member (Item, TStaticText) THEN
  1135.             GetItemType:=VIStatText
  1136.         ELSE IF Member (Item, TIcon) THEN
  1137.             GetItemType:=VIIcon
  1138.         ELSE IF Member (Item, TPicture) THEN
  1139.             GetItemType:=VIPicture
  1140.         ELSE IF Member (Item, TTEView) AND NOT Member (Item, TDialogTEView) THEN
  1141.             GetItemType:=VITextEdit;
  1142.         IF (fGridItemSupport AND GridViewItems) THEN
  1143.         BEGIN 
  1144.             IF Member (Item, TGridView) THEN 
  1145.             BEGIN                                                     
  1146.                 GetItemType:=VIGridItem;
  1147.             END;
  1148.         END;
  1149.     END;
  1150.     
  1151. END;
  1152.  
  1153.  
  1154.  
  1155. {========================================== TGridItem ================================}
  1156.  
  1157. {$S VUAssistSeg}
  1158.  
  1159. { Instantiate a TGridItem object, and fill in its fields..  This is here 
  1160. so it can be overridden if you only want rows or columns to show 
  1161. up as seperate user interface items, instead of each individual cells. }
  1162. PROCEDURE TGridItem.IGridItem (theGridView: TGridView; Rank: integer);
  1163. BEGIN
  1164.     SELF.fGridView:=theGridView;
  1165.     SELF.fRank:=Rank;
  1166.     SELF.fRow:=(Rank-1) DIV theGridView.fNumOfCols +1;
  1167.     SELF.fColumn:=(Rank-1) MOD theGridView.fNumOfCols +1;
  1168. END;
  1169.  
  1170. { Provide the bounding rect of a griditem }
  1171. PROCEDURE TGridItem.GetExtent (VAR itsExtent: VRect);
  1172. VAR
  1173.     aCell: GridCell;
  1174. BEGIN
  1175.     aCell.v:=fRow;
  1176.     aCell.h:=fColumn;
  1177.     fGridView.CellToVRect (aCell, itsExtent);
  1178. END;
  1179.  
  1180.  
  1181. { call the LocalToWindow method of the GridView associated with the griditem }
  1182. PROCEDURE TGridItem.LocalToWindow(VAR thePoint: VPoint);
  1183. BEGIN
  1184.     fGridView.LocalToWindow(thePoint);
  1185. END;
  1186.  
  1187.